package struct;
import java.util.ArrayList;

public class Function implements Identity {

    String name;
    Identity[] args;
    
    public Function(String name, Identity[] args) {
        super();
        this.name = name;
        if (args != null)
        {
            this.args = args;
        }
        else
        {
            this.args = new Identity[0];
        }
    }

    public String getName() {
        return name;
    }

    public Identity[] getArgs() {
        return args;
    }
    
    public Identity getArg(int i) {
        if ( i < args.length)
        {
            return args[i];
        }
        else return null;
    }
    
    public void setArg(Identity ident, int i)
    {
    	if (i < args.length && i > -1)
    	{
    		args[i] = ident;
    	}
    }

    public void setIndex(int idx) {
        for (int i = 0; i < args.length; i++)
        {
            args[i].setIndex(idx);
        }
    }

    public int getMaxIndex() {
       int max = 0;
       
       for (int i = 0; i < args.length; i++)
       {
           if (max < args[i].getMaxIndex())
           {
               max = args[i].getMaxIndex();
           }
       }
       return max;
    }
    
    public ArrayList<Variable> getVariables()
    {
        ArrayList<Variable> vars = new ArrayList<Variable>();
        for (int i = 0; i < args.length; i++)
        {
            if (args[i] instanceof Function)
                vars.addAll(((Function)args[i]).getVariables());
            else if (args[i] instanceof Variable)
                vars.add(((Variable)args[i]));
        }
        
        return vars;
    }
    
    public ArrayList<Function> getFunx()
    {
    	ArrayList<Function> funx = new ArrayList<Function>();
        for (int i = 0; i < args.length; i++)
        {
            if (args[i] instanceof Function)
            {
            	if (!funx.contains((Function)args[i]))
            	{
            		funx.add((Function)args[i]);
            	}
            	ArrayList<Function> temp = ((Function)args[i]).getFunx();
                for (int t = 0; t < temp.size(); t++)
                {
                	if (!funx.contains(temp.get(t)))
                	{
                		funx.add(temp.get(t));
                	}
                }
            }
        }
        
        return funx;
    }

    public String toString()
    {
        StringBuffer sbuf = new StringBuffer(name);
        sbuf.append("(");
        
        for (int i=0; i<args.length-1; i++)
        {
            sbuf.append(args[i]).append(", ");
        }
        sbuf.append(args[args.length-1]).append(")");
        
        return sbuf.toString();
    }
    
    public boolean equals(Object func)
    {
        boolean ret = true;
        
        if (func != null && func instanceof Function)
        {
            if (!((Function) func).getName().equals(name))
            {
                ret = false;
            }
            for (int i = 0; i < args.length; i++)
            {
                if (!args[i].equals(((Function)func).getArg(i)))
                {
                    ret = false;
                }
            }
        }
        else
        {
            ret = false;
        }
        
        return ret;
    }
    
    public Object clone()
    {
    	Identity []clones = new Identity[args.length];
    	for (int i = 0; i<args.length; i++)
    	{
    		clones[i] = (Identity) args[i].clone();
    	}
    	
    	return new Function(name, clones);
    }
}
